/**
 * 资源预加载器
 * 在项目加载阶段预加载所有材质和纹理资源
 * 避免在场景加载时才加载纹理导致的延迟
 */

import * as THREE from '../../lib/three/build/three.module.js';

class ResourcePreloader {
    constructor() {
        // 纹理缓存 - key: texturePath, value: THREE.Texture
        this.textureCache = new Map();
        
        // 材质数据缓存 - key: materialDisplayName, value: materialData
        this.materialDataCache = new Map();
        
        // 加载状态
        this.isLoading = false;
        this.loadedCount = 0;
        this.totalCount = 0;
        
        // 纹理加载器
        this.textureLoader = new THREE.TextureLoader();
        
        // 配置
        this.backendUrl = window.APP_CONFIG?.backendUrl || window.location.origin;
    }
    
    /**
     * 预加载项目的所有资源
     * @param {string} projectId - 项目ID
     * @param {Function} onProgress - 进度回调 (loaded, total)
     * @returns {Promise<Object>} 预加载结果统计
     */
    async preloadProjectResources(projectId, onProgress = null) {
        console.log('🔄 [资源预加载] 开始预加载项目资源...', projectId);
        
        this.isLoading = true;
        this.loadedCount = 0;
        this.totalCount = 0;
        
        const startTime = performance.now();
        
        try {
            // 1. 加载所有材质配置
            console.log('📦 [资源预加载] 步骤 1: 加载材质配置...');
            const materials = await this.loadMaterialConfigs(projectId);
            console.log(`✓ [资源预加载] 找到 ${materials.length} 个材质`);
            
            // 2. 提取所有纹理引用
            console.log('🔍 [资源预加载] 步骤 2: 提取纹理引用...');
            const textureRefs = this.extractTextureReferences(materials);
            console.log(`✓ [资源预加载] 找到 ${textureRefs.size} 个唯一纹理引用`);
            
            // 3. 加载纹理列表
            console.log('📋 [资源预加载] 步骤 3: 加载纹理列表...');
            const textureList = await this.loadTextureList(projectId);
            console.log(`✓ [资源预加载] 纹理库中有 ${textureList.length} 个纹理`);
            
            // 4. 批量预加载纹理
            console.log('📷 [资源预加载] 步骤 4: 预加载纹理...');
            this.totalCount = textureRefs.size;
            
            const loadPromises = [];
            for (const textureRef of textureRefs) {
                const promise = this.preloadTexture(projectId, textureRef, textureList, onProgress);
                loadPromises.push(promise);
            }
            
            await Promise.all(loadPromises);
            
            const elapsedTime = ((performance.now() - startTime) / 1000).toFixed(2);
            console.log(`✅ [资源预加载] 预加载完成！`);
            console.log(`   - 材质数: ${materials.length}`);
            console.log(`   - 纹理数: ${this.textureCache.size}`);
            console.log(`   - 耗时: ${elapsedTime}秒`);
            
            return {
                success: true,
                materialsCount: materials.length,
                texturesCount: this.textureCache.size,
                elapsedTime: parseFloat(elapsedTime)
            };
            
        } catch (error) {
            console.error('❌ [资源预加载] 预加载失败:', error);
            return {
                success: false,
                error: error.message
            };
        } finally {
            this.isLoading = false;
        }
    }
    
    /**
     * 加载项目的所有材质配置
     */
    async loadMaterialConfigs(projectId) {
        try {
            const response = await fetch(`/api/projects/${projectId}/materials`);
            if (!response.ok) {
                throw new Error(`加载材质配置失败: ${response.status}`);
            }
            
            const result = await response.json();
            if (!result.success) {
                throw new Error(result.error || '加载失败');
            }
            
            const materials = result.data || [];
            
            // 缓存材质数据（使用 displayName 作为 key）
            materials.forEach(mat => {
                if (mat.displayName) {
                    this.materialDataCache.set(mat.displayName, mat);
                }
            });
            
            return materials;
        } catch (error) {
            console.error('❌ [资源预加载] 加载材质配置失败:', error);
            return [];
        }
    }
    
    /**
     * 从材质配置中提取所有纹理引用
     */
    extractTextureReferences(materials) {
        const textureRefs = new Set();
        
        // 支持的纹理类型
        const textureProperties = [
            'map',           // 基础颜色贴图
            'normalMap',     // 法线贴图
            'roughnessMap',  // 粗糙度贴图
            'metalnessMap',  // 金属度贴图
            'aoMap',         // 环境光遮蔽贴图
            'emissiveMap',   // 自发光贴图
            'bumpMap',       // 凹凸贴图
            'displacementMap', // 置换贴图
            'alphaMap'       // 透明度贴图
        ];
        
        materials.forEach(material => {
            textureProperties.forEach(prop => {
                if (material[prop]) {
                    textureRefs.add(material[prop]);
                }
            });
        });
        
        return textureRefs;
    }
    
    /**
     * 加载纹理列表
     */
    async loadTextureList(projectId) {
        try {
            const response = await fetch(`/api/projects/${projectId}/textures`);
            if (!response.ok) {
                throw new Error(`加载纹理列表失败: ${response.status}`);
            }
            
            const result = await response.json();
            if (!result.success) {
                throw new Error(result.error || '加载失败');
            }
            
            return result.data || [];
        } catch (error) {
            console.error('❌ [资源预加载] 加载纹理列表失败:', error);
            return [];
        }
    }
    
    /**
     * 预加载单个纹理
     */
    async preloadTexture(projectId, textureRef, textureList, onProgress) {
        try {
            // 查找纹理信息
            const textureInfo = textureList.find(t => 
                t.displayName === textureRef || 
                t.name === textureRef ||
                t.id === textureRef
            );
            
            if (!textureInfo) {
                console.warn(`⚠️ [资源预加载] 未找到纹理: ${textureRef}`);
                this.loadedCount++;
                if (onProgress) onProgress(this.loadedCount, this.totalCount);
                return null;
            }
            
            // 构建纹理URL
            const texturePath = `/api/projects/${projectId}/textures/${textureInfo.id}/file`;
            const textureUrl = `${this.backendUrl}${texturePath}`;
            
            // 检查缓存
            if (this.textureCache.has(texturePath)) {
                console.log(`✓ [资源预加载] 纹理已缓存: ${textureRef}`);
                this.loadedCount++;
                if (onProgress) onProgress(this.loadedCount, this.totalCount);
                return this.textureCache.get(texturePath);
            }
            
            // 加载纹理
            return new Promise((resolve, reject) => {
                this.textureLoader.load(
                    textureUrl,
                    (texture) => {
                        // 设置纹理属性
                        texture.colorSpace = THREE.SRGBColorSpace;
                        texture.wrapS = THREE.RepeatWrapping;
                        texture.wrapT = THREE.RepeatWrapping;
                        
                        // 🔧 修复模糊问题：设置高质量纹理过滤
                        texture.generateMipmaps = true;  // 启用 mipmap 生成
                        texture.minFilter = THREE.LinearMipmapLinearFilter;  // 缩小时使用三线性过滤
                        texture.magFilter = THREE.LinearFilter;              // 放大时使用线性过滤
                        
                        // 🔧 设置各向异性过滤（大幅提升倾斜角度观看时的清晰度）
                        // 尝试获取渲染器的最大各向异性级别，默认使用16
                        const renderer = window.manager?.renderer;
                        const maxAnisotropy = renderer ? renderer.capabilities.getMaxAnisotropy() : 16;
                        texture.anisotropy = maxAnisotropy;
                        
                        // 🔧 标记纹理需要更新（确保设置生效）
                        texture.needsUpdate = true;
                        
                        // ⭐ 缓存纹理：使用多个 key 指向同一个纹理对象，提高缓存命中率
                        // 主 key：使用 ID（标准路径格式）
                        this.textureCache.set(texturePath, texture);
                        
                        // 额外 key：使用 name 和 displayName，方便通过这些字段查找
                        if (textureInfo.name && textureInfo.name !== textureInfo.id) {
                            const nameKey = `/api/projects/${projectId}/textures/${textureInfo.name}/file`;
                            this.textureCache.set(nameKey, texture);
                        }
                        if (textureInfo.displayName && textureInfo.displayName !== textureInfo.id && textureInfo.displayName !== textureInfo.name) {
                            const displayNameKey = `/api/projects/${projectId}/textures/${textureInfo.displayName}/file`;
                            this.textureCache.set(displayNameKey, texture);
                        }
                        
                        this.loadedCount++;
                        if (onProgress) {
                            onProgress(this.loadedCount, this.totalCount);
                        }
                        
                        // console.log(`✓ [资源预加载] 纹理加载完成: ${textureRef} (${this.loadedCount}/${this.totalCount})`);
                        resolve(texture);
                    },
                    undefined,
                    (error) => {
                        console.warn(`⚠️ [资源预加载] 纹理加载失败: ${textureRef}`, error);
                        this.loadedCount++;
                        if (onProgress) onProgress(this.loadedCount, this.totalCount);
                        resolve(null);
                    }
                );
            });
            
        } catch (error) {
            console.error(`❌ [资源预加载] 预加载纹理异常: ${textureRef}`, error);
            this.loadedCount++;
            if (onProgress) onProgress(this.loadedCount, this.totalCount);
            return null;
        }
    }
    
    /**
     * 获取已缓存的纹理
     * @param {string} projectId - 项目ID
     * @param {string} textureNameOrId - 纹理名称或ID
     * @returns {THREE.Texture|null}
     */
    getCachedTexture(projectId, textureNameOrId) {
        if (!textureNameOrId) return null;
        
        // 尝试直接通过路径获取
        const directPath = `/api/projects/${projectId}/textures/${textureNameOrId}/file`;
        if (this.textureCache.has(directPath)) {
            return this.textureCache.get(directPath);
        }
        
        // 遍历查找
        for (const [path, texture] of this.textureCache) {
            if (path.includes(textureNameOrId)) {
                return texture;
            }
        }
        
        return null;
    }
    
    /**
     * 获取已缓存的材质数据
     * @param {string} materialId - 材质的displayName（作为唯一标识）
     */
    getCachedMaterialData(materialId) {
        return this.materialDataCache.get(materialId) || null;
    }
    
    /**
     * 清除所有缓存
     */
    clearCache() {
        console.log('🧹 [资源预加载] 清除缓存...');
        
        // 释放纹理
        this.textureCache.forEach(texture => {
            if (texture && texture.dispose) {
                texture.dispose();
            }
        });
        
        this.textureCache.clear();
        this.materialDataCache.clear();
        this.loadedCount = 0;
        this.totalCount = 0;
        
        console.log('✓ [资源预加载] 缓存已清除');
    }
    
    /**
     * 获取缓存统计信息
     */
    getCacheStats() {
        return {
            textureCount: this.textureCache.size,
            materialCount: this.materialDataCache.size,
            isLoading: this.isLoading,
            progress: this.totalCount > 0 ? (this.loadedCount / this.totalCount) * 100 : 0
        };
    }
}

// 创建单例
const resourcePreloader = new ResourcePreloader();

export default resourcePreloader;

